Starbucks Offer Personalizations

Starbucks Offer Personalizations

In this article, we investigate a set simulated dataset that mimics customer behavior on the Starbucks rewards mobile app. Starbucks tends to send out offers to users of the mobile app once every few days. These offers are exclusive, that is not all users receive the same offer. An offer can contain a discount for their products or sometimes BOGO (buy one get one free). These offers have a validity period before the offer expires. The article here is inspired by a towardsdatascience.com article.

Datasets

The data is contained in three files:

Feature Description in the Datasets
Feature Description
Reward (int) Given reward for completing an offer
Channels (list of strings) Email, mobile app, social media, etc
Difficulty (int) Minimum spending requirement for completing an offer
Duration (int) Time that an offer is valid
Offer Type (string) Type of offer
ID (string) Offer ID
Feature Description
Gender (str) Customers gender
Age (int) Customers age
ID (str) Customers ID
Became Member On (int) Date of membership
Income (float) Customer's income
Feature Description
Person (str) Customer ID
Event (str) Record description
time (int) Time in hours (since the beginning of the study)
Value - (dict of strings) Offer ID or transaction amount

Preprocessing

Portfolio Dataset
Profile Dataset

Age

One possible reason behind having ages over 100 could be misentering age during user registration. To address this issue, we can search for ages over 100 and impute them with median ages.

Became Member On

Note that

Assuming the data is a snapshot of the end of 2018. get member tenure by the number of months.

\begin{align} \text{Member Tenure} =\text{The End of 2018}-\text{Became Member On}\qquad (\text{In Months}) \end{align}

Gender

Income

Imputing NaN values.

Thus,

Transcript Data

Looking at the value column from the Transcript Data, we notice that, this data needs to be processed to be used for our analysis. Thus, we are searching for different key-value pairs. That can be done as follows

Now, we divide offer id into individual columns

Let's look at the resulting DataFrame.

Note that Offer ID appears in two separate columns since there are two different key types for Offer ID. We would like to create a new column to combine the two Offer ID columns.

Merging Transcript with Portfolio to get offer type.

However, this creates some undesired columns that we need to modify

Therefore,

Saving

Problem Description

Effective Offers vs. Ineffective Offers

An offer is considered an effective offers if a customer receives an offer, and then view the received offer, and finally, complete a transaction either BOGO and Discount Offers, or complete a transaction using Informational Offers within the period those offers are valid.

Moroever, an offer that is not classified as effective is considered here as ineffective offers.

Consider the following diagram:

Effective Offers:

Ineffective Offers:

The object of the exercise here is to predict the most suitable offer type that is needed to be sent out to each customer. In doing so, we need to combine the dataset to build a general database that provides a summary of each user's transactional behaviors.

Feature Engineering

Let's introduce some new features.

New Features Full Features name Description
BOGO Offer Rec BOGO Offer Received The number of BOGO offer received
Disc Offer Rec Discount Offer Received The number of Discount offer received
Info Offer Rec Informational Offer Received The number of Informational offer received

As can be seen, not all customers received all offers. Let's investigate this a bit further. Since we have three columns (for the three offers), if we have NaN greater than 2, then it means that the customers haven't received any offers!

We can test the results. For example, for the first user from No_Offer_List, we have

Adding more features to User_Data dataframe, we can introduce new parameters.

New Features Full Features name Description
Tot Tran Cnt Total Transaction Count Whether or not an offer incentivized a transaction
Tot Tran Amnt Total Transaction Amount Total transaction amount
Tot Rewards Rec Total Rewards Received The number of received rewards from an offer type
Ave Tran Amnt Average Transaction Amount Total transaction amount (TTA) / Total transaction count (TTC)
Total Transaction Count
Total Transaction Amount
Total Reward Received
Average Transaction Amount
\begin{align} \text{Average Transaction Amount}=\frac{\text{Total Transaction Amount}}{\text{Total Transaction Count}} \end{align}

Now we add more parameters to the User Data dataframe.

New Features Full Features name Description
Tran Comp NO off Transactions Count without any Offers The number of transactions for a user completes without an offer
Tran Comp off Transactions Count with Offers The number of transactions for a user completes with an offer
Tran Amnt NO off Transactions Amount without any Offers The amount of transactions for a user completes without an offer
Tran Amnt off Transactions Amount with Offers The amount of transactions for a user completes with an offer
Offer Tran Cnt Ratio Offer Transactions Count Ratio Transaction count incentivized by offer / Total number of transactions - TC Of/TTC
Offer Tran Amnt Ratio Offer Transactions Amount Ratio Transaction amount incentivized by offer / Total amount of transactions - TA Of/TTA
Offer Comp View Ratio Offer Completed View Ratio The number of offer completed / the number of offer viewed
Offer Comp Rec Ratio Offer Completed Receive Ratio The number of offers completed/ the number of offers received
Tran Amnt per Offer Transactions Amount per Offer The total transaction amount with offer/ Total number of transactions with an offer
Reward per Offer Reward per Offer Total rewards received / the number of offer completed
BOGO Comp BOGO Completed The number of offer completed for BOGO offer after viewing the BOGO offer
Disc Comp Discount Completed The number of offer completed for Discount offer after viewing the Discount offer
Info Comp Information Completed The number of offer completed for Information offer after viewing the Information offer
BOGO Conv BOGO offer conversion rate The number of BOGO offers completed / The number of BOGO offer received - BOGO Comp/BOGO OR
Info Conv Information offer conversion rate The number of Information offers completed / The number of Information offer received - Info Comp/Info OR
Disc Conv Discount offer conversion rate The number of Discount offers completed / The number of Discount offer received - Disc Comp/Disc OR

Given the fact that there is no explicit offer conversion for the parameters that just being introduced. We need to use nested loops based on the number of offer completed transaction and transactions amount from the offer conversion.

We can create a function, User_Record that takes a user_id and gives all user records as a DataFrame. Then, this function is used to investigate the data based on assumptions that were made at the beginning of this section.

For example, we can try

and get all records of '68be06ca386d4c31939f3a4f0e3dd783'

Creating a Dictionary for the customer journey

Note: This might take some time to process!

Once the searching process has been completed, we can convert the output to a data frame.

Now, \begin{align} \mbox{BOGO Offer} &= \begin{cases} 0 &\mbox{if BOGO_comp is NaN} \\1 & \mbox{else}\end{cases}\\ \mbox{Disc offer} &= \begin{cases} 0 &\mbox{if Disc_comp is NaN} \\1 & \mbox{else}\end{cases}\\ \mbox{Info offer} &= \begin{cases} 0 &\mbox{if Info_comp is NaN} \\1 & \mbox{else}\end{cases} \end{align}

Merging the current dataframe, Person_Off_Trans_df, with the User_Data dataframe.

Creating a column No Offer such that

$$\text{No Offer}= \begin{cases} 1, & \mbox{if there is no offer} \\ 0, & \mbox{if there is at least an offer (BOGO, Discount, Informational)}. \end{cases} $$

For example, we can see the customer that had no offers:

Some Additional Features

\begin{align*} \text{Offer Transaction Count Ratio} &= \frac{\text{Offer Completed}}{\text{Total Transaction Count}},\\ \text{Total Transaction Amount} &= \frac{\text{Offer Transaction Amount}}{\text{Total Transaction Amount}},\\ \text{Offer Transaction Amount Ratio} &= \frac{\text{Offer Transaction Amount}}{\text{Total Transaction Amount}},\\ \text{Viewed Offer Completed Ratio} &= \frac{\text{Offer Completed}}{\text{Offer Viewed}},\\ \text{Transaction Amount per Offer} &= \frac{\text{Offer Transaction Amount}}{\text{Offer Completed}},\\ \text{Reward per offer} &= \frac{\text{Total Reward Received}}{\text{Offer Completed}},\\ \text{Difficulty per Offer} &= \frac{\text{Offer Difficulty}}{\text{Offer Completed}}. \end{align*}

In some cases, customers receive rewards without completing any offers. To correct those values, we amount Total Rewards Received and Total Rewards Received values to zero where Offer Completed is zero!

Moreover,

Saving

Features with high variance

Moreover, high variance for some features can hurt our modeling process. For this reason, we would like to standardize features by removing the mean and scaling to unit variance.

Feature Correlation